#include <stdbool.h>
#include "at_common.h"
#include "main.h"
#include "usart.h"
#include "app_debug.h"


#define AT_UART huart3
#define AT_UART_RECV_SIZE 300
#define AT_UART_SEND_SIZE 500
#define MAX_RECV_BUF_LEN  300

static StreamBufferHandle_t stream_at_send=NULL;
static StreamBufferHandle_t stream_at_recv=NULL;
static bool inited=false;

bool at_uart_deinit()
{
    AT_DEBUG("at uart deinit");
    inited=false;
    __HAL_UART_DISABLE_IT(&AT_UART,UART_IT_TXE);
    __HAL_UART_DISABLE_IT(&AT_UART,UART_IT_RXNE);
    if(stream_at_send!=NULL)
    {
        vStreamBufferDelete(stream_at_send);
        stream_at_send=NULL;
    }
    if(stream_at_recv!=NULL)
    {
        vStreamBufferDelete(stream_at_recv);
        stream_at_recv=NULL;
    }
    AT_DEBUG("at uart deinit ok");
    return true;
}

bool at_uart_init()
{
    AT_DEBUG("at uart init");
    if(inited)
    {
        AT_DEBUG("at uart have been inited");
        return true;
    }
    stream_at_send=xStreamBufferCreate(AT_UART_SEND_SIZE,1);
    if(stream_at_send==NULL)goto AT_UART_INIT_ERROR;

    stream_at_recv=xStreamBufferCreate(AT_UART_RECV_SIZE,1);
    if(stream_at_recv==NULL)goto AT_UART_INIT_ERROR;
    
    __HAL_UART_ENABLE_IT(&AT_UART, UART_IT_RXNE);
    
    inited=true;
    return true;

AT_UART_INIT_ERROR:
    at_uart_deinit();
    return false;
}


uint32_t at_uart_send(const void *data, uint32_t size, uint32_t timeout)
{
    if((inited==false)||(stream_at_send==NULL))
    {
        AT_DEBUG("at uart not init");
        return 0;
    }
    uint32_t write_len=xStreamBufferSend(stream_at_send,data,size,pdMS_TO_TICKS(timeout));
    __HAL_UART_ENABLE_IT(&AT_UART, UART_IT_TXE);
    return write_len;
}

uint32_t at_uart_receive(void *data, uint32_t expect_size,uint32_t timeout)
{
    if((inited==false)&&(stream_at_recv==NULL))
    {
        AT_DEBUG("at uart not init");
        return 0;
    }
    uint32_t read_len=xStreamBufferReceive(stream_at_recv,data,expect_size,pdMS_TO_TICKS(timeout));
    return read_len;
}


void at_uart_irq_handler()
{
	uint8_t ch;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if (__HAL_UART_GET_FLAG(&AT_UART, UART_FLAG_RXNE) != RESET)
    {
        ch = (uint8_t)(AT_UART.Instance->RDR & 0x00FF);
        if(stream_at_recv!=NULL)
        {
            xStreamBufferSendFromISR(stream_at_recv,&ch,1,&xHigherPriorityTaskWoken);
        }
        

    }
    if (__HAL_UART_GET_FLAG(&AT_UART, UART_FLAG_TXE) != RESET)
    {
        __HAL_UART_CLEAR_FLAG(&AT_UART, UART_FLAG_TXE);
        if(stream_at_send!=NULL)
        {
            if(xStreamBufferReceiveFromISR(stream_at_send,&ch,1,&xHigherPriorityTaskWoken))
            {
                AT_UART.Instance->TDR=ch;
            }
            else
            {
                __HAL_UART_DISABLE_IT(&AT_UART,UART_IT_TXE);
            }    
        }
        else
        {
            __HAL_UART_DISABLE_IT(&AT_UART,UART_IT_TXE);
        }
    }
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

